(ns clj-8583.business)

(defn- dateconverter
  [x]
  (let [dateformat1 (java.text.SimpleDateFormat. "MMddhhmmss")
        dateformat2 (java.text.SimpleDateFormat. "yyyy-MM-dd HH:mm:ss")
        datex (.parse dateformat1 x (java.text.ParsePosition. 0))]
    (.setYear datex (.getYear (java.util.Date.)))
    (.format dateformat2 datex)))


(defn- read-buflen
  [reader]
  (let [buf (byte-array 8)]
    (.read reader buf 0 8)
    ;(Integer/parseInt (String. buf (java.nio.charset.Charset/forName "GB2312")))))
    (Integer/parseInt (String. buf "iso8859-1"))))

(defn- send-and-recv
  [servername port data]
  (with-open [client (java.net.Socket. servername port)
              reader (.getInputStream client)
              writer (.getOutputStream client)]
    (.write writer (.getBytes (str (format "%08d" (count data)) data)))
    (.flush writer)
    (let [buflen (read-buflen reader)
          buf (byte-array buflen)]
      (.read reader buf 0 buflen)
      ;(String. buf (java.nio.charset.Charset/forName "GB2312")))))
      (String. buf "iso8859-1"))))

(def business-message-definitions
{:01
  {:0000
    {:req [{:name "trade-code", :pos 0, :length 4, :default "3001"}
            {:name "institude-code", :pos 4, :length 2, :default "A8"}
            {:name "branch-code", :pos 6, :length 30, :default (format "%30s" "87080")}
            {:name "teller-id", :pos 36, :length 10, :default (format "%10s" "111003")}
            {:name "stan", :pos 46, :length 16}
            {:name "user-code", :pos 66, :length 20}
            {:name "month", :pos 86, :length 8, :default "99999999"}],
     :res [{:name "ret-code", :pos 0, :length 4}
            {:name "user-name", :pos 24, :length 96, :union-len 200}
            {:name "address", :pos 120, :length 128, :union-len 320}
            {:name "amount", :pos 310, :length 12, :union-len 12, :func (fn [x] (clojure.string/replace x #"\." ""))}],
;     :recv-data (fn [x] (str "你好" (format "%528s" " "))),
     :recv-data (fn [x]
		  (let [x1 (clojure.string/trim (subs x 24 120))
                        x2 (clojure.string/trim (subs x 120 248))
                        ;x3 (.toString (Integer/parseInt (clojure.string/trim (clojure.string/replace (subs x 310 322) #"\." ""))))
			;x5 (format "%12d" (Integer/parseInt (clojure.string/trim (clojure.string/replace (subs x 316 328) #"\." ""))))
			x5 (format "%12d" (- 0 (Integer/parseInt (clojure.string/trim (clojure.string/replace (subs x 316 328) #"\." "")))))
                        x4 (format "%12d" (Integer/parseInt (clojure.string/trim (clojure.string/replace (subs x 304 316) #"\." ""))))
			;x3 (if (= "           0" x4) (str "D" x5) (str "C" x4))
			x3 (if (= "           0" x4) (str "C" x5) (str "C" x4))
                        len1 (count x1)
                        len2 (count x2)]
                    (prn "aaaaaaaaaaaaa " x1 x2 x3)
	                  (prn "bbbbbbb   " x4)
                    (prn "bbbbbbb   " x5)
                    ;(str x1 (if (> (- 200 len1) 0) (format (str "%" (- 200 len1) "s") " "))
                    (str x1 (if (> (- 199 len1) 0) (format (str "%" (- 199 len1) "s") " "))
                         x2 (if (> (- 320 len2) 0) (format (str "%" (- 320 len2) "s") " "))
                         ;x3 (if (> (- 12 (count x3)) 0) (format (str "%" (- 12 (count x3)) "s") " "))))),
                         x3 (if (> (- 13 (count x3)) 0) (format (str "%" (- 13 (count x3)) "s") " "))))),
		  ;(str (format "%200s" (subs x 24 120)) (format "%320s" (subs x 120 248)) (format "%12s" (clojure.string/replace (subs x 310 322) #"\." "")))),
     ;:send-data (fn [{:keys [stan]} {:keys [user-code]}]
     ;            {"stan" (clojure.string/trim stan), "user-code" (clojure.string/trim user-code)})},
     :send-data (fn [{:keys [stan additional-data-private]}]
                  {"stan" (clojure.string/trim stan), "user-code" (clojure.string/trim (subs additional-data-private 4 44))})},
   :0001
     {:req [{:name "trade-code", :pos 0, :length 4, :default "3006"}
            {:name "institude-code", :pos 4, :length 2, :default "A8"}
            {:name "branch-code", :pos 6, :length 30, :default (format "%30s" "87080")}
            {:name "teller-id", :pos 36, :length 10, :default (format "%10s" "111003")}
            {:name "stan", :pos 46, :length 16}
            {:name "user-code", :pos 66, :length 20}
            {:name "month", :pos 86, :length 8, :default "99999999"}
            {:name "amount", :pos 94, :length 12, :conv (fn [x] (.toString (/ (Long/parseLong x) 100.0)))}
            {:name "pay-type", :pos 106, :length 4, :default "  01"}
            {:name "account", :pos 110, :length 20, :default (format "%20s" " ")}
            {:name "invoice", :pos 130, :length 20, :default (format "%20s" " ")}
            {:name "charge-type", :pos 150, :length 2, :default " 0"}
            {:name "date", :pos 152, :length 19, :conv dateconverter}
            {:name "amt1", :pos 171, :length 12, :default (format "%12s" " ")}
            {:name "amt2", :pos 183, :length 12, :default (format "%12s" " ")}
            {:name "num1", :pos 195, :length 12, :default (format "%12s" " ")}
            {:name "num2", :pos 207, :length 7, :default (format "%7s" " ")}
           ],
      :res [{:name "ret-code", :pos 0, :length 4}],
      :send-data (fn [{:keys [stan additional-data-private transaction-amount transmission-date-time]}]
                   {"stan" stan, "user-code" (clojure.string/trim (subs additional-data-private 4 44)),
                    "date" (dateconverter transmission-date-time), "amount" (.toString (/ (Integer/parseInt transaction-amount) 100.0))})},
   :0002
     {:req [{:name "trade-code", :pos 0, :length 4, :default "3007"}
            {:name "institude-code", :pos 4, :length 2, :default "A8"}
            {:name "branch-code", :pos 6, :length 30, :default (format "%30s" "87080")}
            {:name "teller-id", :pos 36, :length 10, :default (format "%10s" "111003")}
            {:name "stan", :pos 46, :length 16}
            {:name "old-stan", :pos 62, :length 16}
            {:name "old-date", :pos 78, :length 19, :conv dateconverter}],
      :res [{:name "ret-code", :pos 0, :length 4}],
      :send-data (fn [{:keys [stan original-data]}]
                   {"stan" stan, "old-stan" (subs original-data 4 10), "old-date" (dateconverter (subs original-data 10 20))})},
   :errors {"0000" "00", "3030" "E1"}},
 :send-data (fn [x y] (map #(if (:default %) (:default %) (format (str "%" (:length %) "s") (x (:name %)))) y)),
 :recv-data (fn [x y] (str x y)),
 :send-func (fn [x] (send-and-recv "144.212.64.65" 8888 x))
}
)
;(def fds {:stan "1", :transmition-date-time "0804092256", :additional-amounts "100", :additinal-data-private "                   2701001204252               "})
